package cn.tedu.rpc;

import com.rabbitmq.client.*;
import com.rabbitmq.client.AMQP.BasicProperties;

import java.io.IOException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Client {
    static BlockingQueue<Long> bq = new ArrayBlockingQueue<>(10);

    public static void main(String[] args) throws Exception{
        System.out.print("求第几个斐波那契数:");
        int n = new Scanner(System.in).nextInt();
        long fbnqs = fbnqs(n);
        System.out.println("第"+n+"个斐波那契数是:"+fbnqs);
    }
    //异步调用服务器，从服务器种获取结果
    private static long fbnqs(int n) throws Exception {
        //1.通过连接工厂配置rabbitmq的连接信息
        ConnectionFactory cf = new ConnectionFactory();
        cf.setHost("127.0.0.1");
        cf.setPort(5672); //客户端端口，5672是默认端口，可以省略
        cf.setUsername("guest");
        cf.setPassword("guest");
        //2.创建tcp和channel
        Connection nc = cf.newConnection();
        Channel cc = nc.createChannel();
        //3.服务器需要从调用队列中获取调用信息
        cc.queueDeclare("rpc_queue",false,false,false,null);
        cc.queuePurge("rpc_queue");
        //定义返回队列名
        String replyTo = cc.queueDeclare().getQueue();
        //关联ID
        String cid = UUID.randomUUID().toString();
        BasicProperties properties = new BasicProperties().builder()
                .replyTo(replyTo)
                .correlationId(cid)
                .build();
        cc.basicPublish("","rpc_queue",properties,(n+"").getBytes());
        System.out.println("调用信息已发送");
        //模拟执行其他运行
        System.out.println("模拟执行其他运算，不立即等待计算结果");
        //从返回队列种获取计算结果
        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String s, Delivery delivery) throws IOException {
                //处理数据之前，先对比cid
                if(delivery.getProperties().getCorrelationId().equals(cid)){
                  long fbnqs =  Integer.parseInt(new String(delivery.getBody()));
                  bq.offer(fbnqs);
                  cc.getConnection().close();
                }
            }
        };
        CancelCallback cancelCallback = new CancelCallback() {
            @Override
            public void handle(String s) throws IOException {
            }
        };
        cc.basicConsume(replyTo,true,deliverCallback,cancelCallback);
        return bq.take();
    }
}
